package com.wmada.toolkit.rest.builder;

import com.alibaba.fastjson.JSON;
import com.wmada.toolkit.common.FileUtils;
import com.wmada.toolkit.rest.MimeType;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.message.BasicNameValuePair;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author will.ma
 * @date 2019-4-25
 */
@SuppressWarnings("unused")
public class EntityBuilder {

    public static HttpEntity buildJson(Object body, ContentType contentType) {
        return new StringEntity(JSON.toJSONString(body), contentType);
    }

    public static HttpEntity buildFile(File file, ContentType contentType) {
        return new FileEntity(file, contentType);
    }

    public static HttpEntity buildForm(Map<String, String> data, Charset charset) {
        List<NameValuePair> list = new ArrayList<>();
        for (Map.Entry<String, String> entry : data.entrySet()) {
            list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        return new UrlEncodedFormEntity(list, charset);
    }

    public static HttpEntity buildString(String entity, ContentType contentType) {
        return new StringEntity(entity, contentType);
    }

    public static HttpEntity buildJson(Object body) {
        return buildJson(body, ContentType.APPLICATION_JSON);
    }

    public static HttpEntity buildFile(File file) {
        return new FileEntity(file);
    }

    public static HttpEntity buildForm(Map<String, String> data) {
        return buildForm(data, ContentType.APPLICATION_FORM_URLENCODED.getCharset());
    }

    public static HttpEntity buildString(String entity) {
        return new StringEntity(entity, ContentType.TEXT_PLAIN);
    }

    public static HttpEntity buildMultipart(Map<String, String> data) {
        return buildMultipart(data, ContentType.MULTIPART_FORM_DATA.getCharset());
    }

    public static HttpEntity buildMultipart(Map<String, String> data, Charset charset) {
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setCharset(charset);

        for (Map.Entry<String, String> kv : data.entrySet()) {
            multipartEntityBuilder.addTextBody(kv.getKey(), kv.getValue());
        }
        return multipartEntityBuilder.build();
    }

    public static HttpEntity buildMultipart(Map<String, String> data, Charset charset, Map<String, File> files) {
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setCharset(charset);

        for (Map.Entry<String, File> fileEntry : files.entrySet()) {
            File     file     = fileEntry.getValue();
            MimeType mimeType = MimeType.getMimeTypeByExtension(FileUtils.getFileSuffix(file.getName()));
            if (mimeType != null) {
                multipartEntityBuilder.addBinaryBody(fileEntry.getKey(), file, ContentType.create(mimeType.getMime()), file.getName());
            } else {
                multipartEntityBuilder.addBinaryBody(fileEntry.getKey(), file, ContentType.DEFAULT_BINARY, file.getName());
            }
        }
        for (Map.Entry<String, String> kv : data.entrySet()) {
            multipartEntityBuilder.addTextBody(kv.getKey(), kv.getValue());
        }
        return multipartEntityBuilder.build();
    }

    private final Map<String, String> data;

    public EntityBuilder() {
        data = new HashMap<>();
    }

    public EntityBuilder append(String key, String value) {
        data.put(key, value);
        return this;
    }

    public EntityBuilder append(String key, Object value) {
        if(value != null) {
            data.put(key, value.toString());
        }
        return this;
    }

    public EntityBuilder put(String key, String value) {
        data.put(key, value);
        return this;
    }

    public EntityBuilder put(String key, Object value) {
        if(value != null) {
            data.put(key, value.toString());
        }
        return this;
    }

    public HttpEntity buildJson() {
        return buildJson(data, ContentType.APPLICATION_JSON);
    }

    public HttpEntity buildForm() {
        return buildForm(data, ContentType.APPLICATION_FORM_URLENCODED.getCharset());
    }


}
